package com.gwz.cardserver.dto.fight;

import com.gwz.cardserver.consts.CardTypeEnum;
import com.gwz.cardserver.consts.IdentityEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class FightRoom {
    /**
     * 房间id
     */
    private int id;
    /**
     * 所有玩家
     */
    private List<PlayerDto> players;
    /**
     * 中途退出玩家id
     */
    private List<String> leaveUids;
    /**
     * 牌库
     */
    private LibraryModel libraryModel;
    /**
     * 底牌
     */
    private List<CardDto> tableCardList;
    /**
     * 倍数
     */
    private int multiple;
    /**
     * 回合管理
     */
    public RoundModel roundModel;


    public FightRoom(int id, List<String> uids) {
        this.id = id;
        this.players = new ArrayList<>();
        init(uids);
        this.leaveUids = new ArrayList<>();
        this.libraryModel = new LibraryModel();
        this.tableCardList = new ArrayList<>();
        this.multiple = 1;
        this.roundModel = new RoundModel();
    }

    public void init(List<String> uids){
        for (String uid : uids) {
            PlayerDto playerDto = new PlayerDto();
            playerDto.setUserId(uid);
            this.players.add(playerDto);
        }
    }

    /**
     * 是否离线
     * @param uid
     * @return
     */
    public boolean isOffline(String uid){
        return leaveUids.contains(uid);
    }

    /**
     * 转换出牌
     */
    public String turn() {
        String currUid = roundModel.getCurrentUid();
        String nextUid = getNextUid(currUid);
        roundModel.setCurrentUid(nextUid);
        return nextUid;
    }

    /**
     * 计算下一个出牌者
     *
     * @param currUid
     * @return
     */
    public String getNextUid(String currUid) {
        for (int i = 0; i < players.size(); i++) {
            PlayerDto player = players.get(i);
            if (player.getUserId().equals(currUid)) {
                if (i == 2)
                    return players.get(0).getUserId();
                return players.get(i + 1).getUserId();
            }
        }
        throw new IllegalArgumentException("并没有这个出牌者");
    }

    /**
     * 出牌
     *
     * @param type
     * @param weight
     * @param length
     * @param userId
     * @param cards
     * @return
     */
    public boolean deadCard(int type, int weight, int length, String userId, List<CardDto> cards) {
        boolean canDeal = false;

        // 判断出牌能否压制
        // 牌的类型一样 && 权重高的牌管权重小的牌
        if (type == roundModel.getLastCardType() && weight > roundModel.getLastWeight()) {
            // 顺序, 进行长度的限制
            if (type == CardTypeEnum.STRAIGHT.getCode() || type == CardTypeEnum.DOUBLE_STRAIGHT.getCode() || type == CardTypeEnum.TRIPLE_STRAIGHT.getCode()) {
                if (length == roundModel.getLastLength()) {
                    // 满足出牌条件
                    canDeal = true;
                }
            } else {
                // 满足出牌条件
                canDeal = true;
            }
        }
        // 炸弹
        else if (type == CardTypeEnum.BOOM.getCode() && roundModel.getLastCardType() != CardTypeEnum.BOOM.getCode()) {
            canDeal = true;
        }
        // 王炸
        else if (type == CardTypeEnum.JOKER_BOOM.getCode()) {
            canDeal = true;
        }

        if (canDeal) {
            // 移除玩家的手牌
            removeCards(userId, cards);
            // 可能会翻倍
            if (type == CardTypeEnum.BOOM.getCode()) {
                this.multiple *= 4;
            } else if (type == CardTypeEnum.JOKER_BOOM.getCode()) {
                this.multiple *= 8;
            }
            // 保存回合信息
            roundModel.change(length, type, weight, userId);
        }


        return canDeal;
    }

    /**
     * 移除玩家手牌
     *
     * @param userId
     * @param cardDtos
     */
    private void removeCards(String userId, List<CardDto> cardDtos) {
        List<CardDto> currList = getUserCards(userId);

        for (int i = currList.size() - 1; i >= 0; i--) {
            for (CardDto card : cardDtos) {
                if (currList.get(i).getName().equals(card.getName())) {
                    currList.remove(i);
                }
            }
        }
    }

    /**
     * 获取玩家的现有手牌
     *
     * @param userId
     * @return
     */
    public List<CardDto> getUserCards(String userId) {
        for (PlayerDto player : players) {
            if (player.getUserId().equals(userId)) {
                return player.getCardList();
            }
        }
        throw new IllegalArgumentException("不存在这个玩家!");
    }

    /**
     * 发牌
     */
    public void initPlayerCards() {
        // 54 一个人17张
        // 剩三个底牌
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 17; j++) {
                CardDto card = libraryModel.deal();
                players.get(i).addCard(card);
            }
        }

        // 发底牌
        for (int i = 0; i < 3; i++) {
            CardDto cardDto = libraryModel.deal();
            tableCardList.add(cardDto);
        }
    }

    /**
     * 设置地主
     * @param userId
     */
    public void setLandlord(String userId) {
        for (PlayerDto player : players) {
            if (player.getUserId().equals(userId)) {
                // 设置地主身份
                player.setIdentity(IdentityEnum.LANDLORD.getCode());
                // 发底牌
                for (int i = 0; i < tableCardList.size(); i++) {
                    player.addCard(tableCardList.get(i));
                }
                roundModel.start(userId);
            }
        }
    }

    public PlayerDto getPlayerModel(String userId) {
        for (PlayerDto player : players) {
            if (player.getUserId().equals(userId)) {
                return player;
            }
        }
        throw new IllegalArgumentException("没有找到此用户");
    }

    /**
     * 获取用户的身份
     *
     * @param userId
     * @return
     */
    public int getPlayerIdentity(String userId) {
        return getPlayerModel(userId).getIdentity();
    }

    /**
     * 获取相同身份的用户id
     *
     * @param identity
     * @return
     */
    public List<String> getSameIdentityUids(int identity) {
        List<String> uids = new ArrayList<>();
        for (PlayerDto player : players) {
            if (player.getIdentity() == identity) {
                uids.add(player.getUserId());
            }
        }
        return uids;
    }

    /**
     * 获取相同身份的用户id
     *
     * @param identity
     * @return
     */
    public List<String> getNotSameIdentityUids(int identity) {
        List<String> uids = new ArrayList<>();
        for (PlayerDto player : players) {
            if (player.getIdentity() != identity) {
                uids.add(player.getUserId());
            }
        }
        return uids;
    }

    /**
     * 获取房间内的第一个玩家的id
     *
     * @return
     */
    public String getFirstUid() {
        return players.get(0).getUserId();
    }

    /**
     * 排序手牌
     *
     * @param cards
     * @param asc
     */
    private void sortCard(List<CardDto> cards, boolean asc) {
        //jobs.sort(Comparator.comparing(Job::getId));
        if (asc)
            cards.sort(Comparator.comparing(CardDto::getWeight));
        else
            cards.sort(Comparator.comparing(CardDto::getWeight).reversed());
    }

    /**
     * 排序牌
     * @param asc
     */
    public void sort(boolean asc) {
        // 排序玩家手牌
        for (PlayerDto player : players) {
            sortCard(player.getCardList(),asc);
        }
        // 排序地主牌
        sortCard(tableCardList,asc);
    }
}
